/*****************************************************************************
 *  CommLayerLib - Logger.java
 *  Copyright (C) 2012  Matteo Piscitelli
 *  E-mail: matteo@picciux.it
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further info, check http://code.google.com/p/java-comm-layer/
 *
 *  SVN: $Id: Logger.java 50 2012-10-23 15:48:13Z picciux@gmail.com $
 *  
 *****************************************************************************/

package it.picciux.commlayer.log;

import java.util.Vector;

/**
 * Class for logging
 * @author 00688263
 *
 */
public abstract class Logger {
	public interface ILoggerFactory {
		public Logger getLoggerImpl(String moduleName, int type, Object[] params) throws LoggerException;
	}
	
	private static ILoggerFactory factory = null;
	private static Vector loggers = new Vector();

	public static Logger getLogger(String moduleName, int type, Object[] params) throws LoggerException {
		return getLogger(moduleName, type, params, false);
	}
		
	public static Logger getLogger(String moduleName, int type, Object[] params, boolean debug) throws LoggerException {
		if (debug) System.out.println("Someone asked for logger '" + moduleName + "'");
		
		for (int i = 0; i < loggers.size(); i++)
			if (((Logger) loggers.elementAt(i)).getModuleName().equals(moduleName)) {
				if (debug) System.out.println("Returning an already existent logger");
				return ((Logger) loggers.elementAt(i));
			}

		
		Logger ret = null;
		
		if (factory == null || type == NULL) {
			if (debug) System.out.println("Factory or type is null");
			ret = getNullLogger(moduleName);
		} else {
			if (debug) System.out.println("Returning new logger from factory");
			ret = factory.getLoggerImpl(moduleName, type, params);
		}
		
		loggers.addElement(ret);
		return ret; 
	}
	
	public static Logger getNullLogger(String moduleName) {
		NullLogger nl = new NullLogger(moduleName);
		loggers.addElement(nl);
		return nl;
	}
	
	public static void init(ILoggerFactory loggerFactory) {
		factory = loggerFactory;
	}
	
	public static final int ALL			= -1;
	public static final int FINEST 		= 0;
	public static final int FINER		= 1;
	public static final int FINE 		= 2;
	public static final int CONFIG 		= 3;
	public static final int INFO 		= 4;
	public static final int WARNING 	= 5;
	public static final int SEVERE 		= 6;
	public static final int OFF 		= 7;
	
	public static final int NULL		= 0;
	public static final int CONSOLE		= 1;
	public static final int FILE		= 2;
	public static final int SOCKET		= 3;
	public static final int STREAM		= 4;
	public static final int SERVER		= 5;
	
	protected String modName = null;
	private int level = WARNING;
	
	public Logger(String moduleName) {
		this.modName = moduleName;
	}
	
	public boolean setLevel(int logLevel) {
		if (logLevel < FINEST || logLevel > SEVERE) return false;
		
		level = logLevel;
		finest("Set " + level + " for logger '" + modName + "'");
		return true;
	}

	public int getLevel() {
		return level;
	}
	
	public boolean isLoggable(int logLevel) {
		return ! ((logLevel < level) || (logLevel < FINEST) || (logLevel > SEVERE));
	}
	
	public String getModuleName() {
		return modName;
	}
	
	public abstract void log(int logLevel, String msg);
	public abstract void log(int logLevel, String msg, Object param1);
	public abstract void log(int logLevel, String msg, Object[] params);
	public abstract void log(int logLevel, String msg, Throwable throwable);
	public abstract void logp(int logLevel, String className, String methodName, String msg);
	public abstract void logp(int logLevel, String className, String methodName, String msg, Object param1);
	public abstract void logp(int logLevel, String className, String methodName, String msg, Object[] params);
	public abstract void logp(int logLevel, String className, String methodName, String msg, Throwable throwable);
	
	public abstract void finest(String msg);
	public abstract void finer(String msg);
	public abstract void fine(String msg);
	public abstract void config(String msg);
	public abstract void info(String msg);
	public abstract void warning(String msg);
	public abstract void severe(String msg);
	public abstract void entering(String className, String methodName);
	public abstract void entering(String className, String methodName, Object param1);
	public abstract void entering(String className, String methodName, Object[] params);
	public abstract void exiting(String className, String methodName);
	public abstract void exiting(String className, String methodName, Object retValue);
	
	
}
